// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial

import { ColorSchemeSelector } from "color-scheme.slint";

export global Palette  {
    in-out property<bool> dark-color-scheme: ColorSchemeSelector.dark-color-scheme;

    // The colors in light mode are default palette. In the
    // Fluent UI Theme Designer they match the colors produced
    // with Primary Color = #0078d4, Text Color = #201f1e and Background Color = #ffffff
    // The dark mode colors are produced in the Fluent UI Theme Designer by swapping
    // Text Color and Background Color from light mode, applying the variations below
    // and darkening the "white" and brightening the "neutralLight" variants for improved
    // contrast (esp. on buttons).

    out property<color> themeDarker: #004578;
    out property<color> themeDark: #005a9e;
    out property<color> themeDarkAlt: #106ebe;
    out property<color> themePrimary: #0078d4;
    out property<color> themeSecondary: #2b88d8;
    out property<color> themeTertiary: #71afe5;
    out property<color> themeLight: #c7e0f4;
    out property<color> themeLighter: #deecf9;
    out property<color> themeLighterAlt: #eff6fc;
    out property<color> black: !root.dark-color-scheme ? #000000 : #f8f8f8;
    out property<color> blackTranslucent40: rgba(0,0,0,0.4);
    out property<color> neutralDark: !root.dark-color-scheme ? #201f1e : #f4f4f4;
    out property<color> neutralPrimary: !root.dark-color-scheme ? #323130 : #ffffff;
    out property<color> neutralPrimaryAlt: !root.dark-color-scheme ? #3b3a39 : #dadada;
    out property<color> neutralSecondary: !root.dark-color-scheme ? #605e5c : #d0d0d0;
    out property<color> neutralSecondaryAlt: #8a8886;
    out property<color> neutralTertiary: !root.dark-color-scheme ? #a19f9d : #c8c8c8;
    out property<color> neutralTertiaryAlt: !root.dark-color-scheme ? #c8c6c4 : #6d6d6d;
    out property<color> neutralQuaternary: #d2d0ce;
    out property<color> neutralQuaternaryAlt: !root.dark-color-scheme ? #e1dfdd : #484848;
    out property<color> neutralLight: !root.dark-color-scheme ? #edebe9 : #3f3f3f;
    out property<color> neutralLighter: !root.dark-color-scheme ? #f3f2f1 : #313131;
    out property<color> neutralLighterAlt: !root.dark-color-scheme ? #faf9f8 : #282828;
    out property<color> accent: #0078d4;
    out property<color> white: !root.dark-color-scheme ? #ffffff : #1f1f1f;
    out property<color> whiteTranslucent40: rgba(255,255,255,0.4);
    out property<color> yellowDark: #d29200;
    out property<color> yellow: #ffb900;
    out property<color> yellowLight: #fff100;
    out property<color> orange: #d83b01;
    out property<color> orangeLight: #ea4300;
    out property<color> orangeLighter: #ff8c00;
    out property<color> redDark: #a4262c;
    out property<color> red: #e81123;
    out property<color> magentaDark: #5c005c;
    out property<color> magenta: #b4009e;
    out property<color> magentaLight: #e3008c;
    out property<color> purpleDark: #32145a;
    out property<color> purple: #5c2d91;
    out property<color> purpleLight: #b4a0ff;
    out property<color> blueDark: #002050;
    out property<color> blueMid: #00188f;
    out property<color> blue: #0078d4;
    out property<color> blueLight: #00bcf2;
    out property<color> tealDark: #004b50;
    out property<color> teal: #008272;
    out property<color> tealLight: #00b294;
    out property<color> greenDark: #004b1c;
    out property<color> green: #107c10;
    out property<color> greenLight: #bad80a;
    out property<color> primaryGradient: @radial-gradient(circle, themePrimary 0%, white 100%);
}


export global StyleMetrics  {
    out property<length> layout-spacing: 8px;
    out property<length> layout-padding: 8px;
    out property<length> text-cursor-width: 2px;
    out property<color> window-background: Palette.white;
    out property<color> default-text-color: Palette.neutralDark;
    out property<color> textedit-background: Palette.white;
    out property<color> textedit-text-color: Palette.neutralPrimary;
    out property<color> textedit-background-disabled: Palette.neutralLighter;
    out property<color> textedit-text-color-disabled: Palette.neutralTertiary;
    out property<bool> dark-color-scheme: Palette.dark-color-scheme;
}

export component Button {
    callback clicked;
    in property<string> text <=> text.text;
    out property<bool> has-focus: fs.has-focus;
    out property<bool> pressed: self.enabled && touch.pressed;
    in property<bool> enabled <=> touch.enabled;
    in property<bool> checkable;
    in-out property<bool> checked;
    in property<image> icon;
    in property <bool> primary;

    accessible-role: button;
    accessible-label <=> text.text;

    Rectangle {
        border-width: root.primary ? 0 : 1px;
        border-radius: 2px;
        border-color: !root.enabled ? Palette.neutralLighter : Palette.neutralSecondaryAlt;
        background: !root.enabled ? Palette.neutralLighter
            : (touch.pressed || root.checked) ? Palette.neutralLight
            : touch.has-hover ? Palette.neutralLighter
            : root.primary ? Palette.accent : Palette.white;
    }
    horizontal-stretch: 0;
    vertical-stretch: 0;
    min-height: max(32px, l.min-height);
    l := HorizontalLayout {
        padding-left: 16px;
        padding-right: 16px;
        spacing: 8px;
        padding-top: 3px;
        padding-bottom: 3px;

        if (root.icon.width > 0 && root.icon.height > 0): Image {
            source <=> root.icon;
            width: 24px;
        }

        text := Text {
            color: !root.enabled ? Palette.neutralTertiary : Palette.neutralDark;
            horizontal-alignment: center;
            vertical-alignment: center;
            font-weight: 600;
        }
    }

    touch := TouchArea {
        clicked => {
            if (root.checkable) {
                root.checked = !root.checked;
            }
            root.clicked();
        }
    }

    fs := FocusScope {
        x:0;
        width: 0px; // Do not react on clicks
        enabled <=> root.enabled;
        key-pressed(event) => {
            if (event.text == " " || event.text == "\n") {
                 touch.clicked();
                 return accept;
            }
            return reject;
        }
    }

    Rectangle { // Focus rectangle
        x: 3px;
        y: self.x;
        width: parent.width - 2*self.x;
        height: parent.height - 2*self.y;
        border-width: root.enabled && root.has-focus? 1px : 0px;
        border-color: Palette.black;
    }
}

component ScrollBar inherits Rectangle {
    background: enabled ? Palette.white : Palette.neutralLighter;
   // border-color: Palette.button-background;
    border-width: 1px;
    in-out property <bool> horizontal;
    in-out property<length> maximum;
    in-out property<length> page-size;
    // this is always negative and bigger than  -maximum
    in-out property<length> value;
    in property <bool> enabled;

    handle := Rectangle {
        width: !root.horizontal ? parent.width : root.maximum <= 0phx ? 0phx : max(32px, parent.width * root.page-size / (root.maximum + root.page-size));
        height: root.horizontal ? parent.height : root.maximum <= 0phx ? 0phx : max(32px, parent.height * (root.page-size / (root.maximum + root.page-size)));

        border-radius: (root.horizontal ? self.height : self.width) / 2;
        background: touch-area.pressed ? Palette.themePrimary :
            touch-area.has-hover ? Palette.themeSecondary : Palette.neutralTertiary;
        x: !root.horizontal ? 0phx : (root.width - handle.width) * (-root.value / root.maximum);
        y: root.horizontal ? 0phx : (root.height - handle.height) * (-root.value / root.maximum);
    }
    touch-area := TouchArea {
        width: parent.width;
        height: parent.height;
        property <length> pressed-value;
        pointer-event(event) => {
            if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
                self.pressed-value = -root.value;
            }
        }
        moved => {
            if (self.enabled && self.pressed) {
                root.value = -max(0px, min(root.maximum, self.pressed-value + (
                    root.horizontal ? (touch-area.mouse-x - touch-area.pressed-x) * (root.maximum / (root.width - handle.width))
                               : (touch-area.mouse-y - touch-area.pressed-y) * (root.maximum / (root.height - handle.height))
                )));
            }
        }
    }
}

export component ScrollView {
    in-out property <length> viewport-width <=> fli.viewport-width;
    in-out property <length> viewport-height <=> fli.viewport-height;
    in-out property <length> viewport-x <=> fli.viewport-x;
    in-out property <length> viewport-y <=> fli.viewport-y;
    out property <length> visible-width <=> fli.width;
    out property <length> visible-height <=> fli.height;
    in property <bool> enabled: true;
    // FIXME: remove. This property is currently set by the ListView and is used by the native style to draw the scrollbar differently when it has focus
    in-out property <bool> has-focus;
    min-height: 50px;
    min-width: 50px;
    horizontal-stretch: 1;
    vertical-stretch: 1;
    preferred-height: 100%;
    preferred-width: 100%;

    Rectangle {
        border-radius: 2px;
        border-width: !root.enabled ? 0px : root.has-focus ? 2px : 1px;
        border-color: !root.enabled ? Palette.neutralLighter
            : root.has-focus ? Palette.themeSecondary
            : Palette.neutralPrimary;
    }

    fli := Flickable {
        @children
        x: 2px;
        y: 2px;
        interactive: false;
        viewport-y <=> vbar.value;
        viewport-x <=> hbar.value;
        width: parent.width - vbar.width - 4px;
        height: parent.height - hbar.height - 4px;
    }
    vbar := ScrollBar {
        enabled: root.enabled;
        width: 16px;
        x: fli.width + fli.x;
        y: fli.y;
        height: fli.height;
        horizontal: false;
        maximum: fli.viewport-height - fli.height;
        page-size: fli.height;
    }
    hbar := ScrollBar {
        enabled: root.enabled;
        height: 16px;
        y: fli.height + fli.y;
        x: fli.x;
        width: fli.width;
        horizontal: true;
        maximum: fli.viewport-width - fli.width;
        page-size: fli.width;
    }
    corner := Rectangle {
        x: fli.width + fli.x;
        y: fli.height + fli.y;
        height: 16px;
        width: 16px;
        background: root.enabled ? transparent : Palette.neutralLighter;
    }
}

export component Switch {
    callback toggled;

    in property <string> text <=> label.text;
    in-out property <bool> checked: true;
    out property <bool> has-focus: fs.has-focus;
    in property<bool> enabled: true;

    min-width: 40px;
    min-height: 20px;
    vertical-stretch: 0;
    horizontal-stretch: 0;
    accessible-label <=> label.text;
    accessible-checkable: true;
    accessible-checked <=> root.checked;
    accessible-role: checkbox;
    forward-focus: fs;

    layout := HorizontalLayout {
        spacing: 8px;

        VerticalLayout {
            alignment: center;

           Rectangle {
                width: 40px;
                height: 20px;

                track := Rectangle {
                    border-radius: 10px;
                    border-width: 1px;
                    border-color: Palette.neutralSecondaryAlt;
                }

                handle := Rectangle {
                    x: 3px;
                    y: (parent.height - self.height) / 2;
                    width: 14px;
                    height: self.width;
                    border-radius: self.width / 2;
                    background: Palette.neutralSecondaryAlt;

                    animate background, x { duration: 200ms; easing: linear; }
                }

                animate background, border-color { duration: 200ms; easing: linear; }
            }
        }

        label := Text {
            color: !root.enabled ? Palette.neutralTertiary : Palette.neutralDark;
            horizontal-alignment: left;
            vertical-alignment: center;
            vertical-stretch: 1;
        }
    }

    touch := TouchArea {
        enabled <=> root.enabled;

        clicked => {
            root.toggle-checked();
        }
    }

    fs := FocusScope {
        x:0;
        width: 0px; // Do not react on clicks
        enabled <=> root.enabled;

        key-pressed(event) => {
            if (event.text == " " || event.text == "\n") {
                 root.toggle-checked();
                 return accept;
            }
            return reject;
        }
    }

    Rectangle { // Focus rectangle
        x: -3px;
        y: self.x;
        width: parent.width - 2 * self.x;
        height: parent.height - 2 * self.y;
        border-width: root.enabled && root.has-focus ? 1px : 0px;
        border-color: Palette.black;
    }

    function toggle-checked() {
        if(!root.enabled) {
            return;
        }

        root.checked = !root.checked;
        root.toggled();
    }

    states [
        disabled-selected when !root.enabled && root.checked  : {
            handle.x: track.width - handle.width - 3px;
            handle.background: Palette.neutralTertiary;
            track.border-color: Palette.neutralLighter;
            track.background: Palette.neutralLighter;
        }
        disabled when !root.enabled : {
            handle.background: Palette.neutralQuaternaryAlt;
            track.border-color: Palette.neutralQuaternaryAlt;
        }
        pressed-hover when (touch.pressed || touch.has-hover) && !root.checked : {
            handle.background: Palette.neutralTertiary;
            track.border-color: Palette.neutralTertiary;
        }
        selected when root.checked : {
            handle.x: track.width - handle.width - 3px;
            handle.background: Palette.white;
            track.background:  Palette.themePrimary;
            track.border-color:  Palette.themePrimary;
        }
    ]
}
